#ifndef _SCOPEGUARD_HPP_
#define _SCOPEGUARD_HPP_

#include <type_traits>

// ScopeGuard类：用于确保在作用域结束时执行清理操作
// 模板参数F通常是一个函数或者可调用对象
//记住一个原则：凡是需要配对的操作（开启/关闭、分配/释放、加锁/解锁），
//都可以用 ScopeGuard 来确保第二个操作一定会执行。
template <typename F>
class ScopeGuard
{
public:
	// 移动构造函数：接受右值引用参数
	explicit ScopeGuard( F && f) : m_func(std::move(f)), m_dismiss(false){}
	// 拷贝构造函数：接受常量左值引用参数
	explicit ScopeGuard(const F& f) : m_func(f), m_dismiss(false){}

	// 析构函数：如果没有被dismiss，则执行存储的函数
	~ScopeGuard()
	{
		if (!m_dismiss)
			m_func();
	}
	// 移动赋值操作符：转移所有权并使原对象失效
	ScopeGuard(ScopeGuard && rhs) : m_func(std::move(rhs.m_func)),
		m_dismiss(rhs.m_dismiss)
	{
		rhs.Dismiss();
	}

	// Dismiss方法：取消在析构时执行函数
	void Dismiss()
	{
		m_dismiss = true;
	}

private:
	F m_func;        // 存储需要执行的函数或可调用对象
	bool m_dismiss;   // 标记是否取消执行

	// 禁用默认构造函数和拷贝操作
	ScopeGuard();
	ScopeGuard(const ScopeGuard&);
	ScopeGuard& operator=(const ScopeGuard&);
};

// 辅助函数：创建ScopeGuard对象的工厂函数
// std::decay用于移除引用和cv限定符，获得原始类型
template <typename F>
ScopeGuard<typename std::decay<F>::type> MakeGuard(F && f)
{
	return ScopeGuard<typename std::decay<F>::type>(std::forward<F>(f));
}

#endif  //_SCOPEGUARD_HPP_